package com.jiawei.链表.单链表;

import com.jiawei.链表.LinkedList;

import java.util.function.Consumer;

/**
 * @author : willian fu
 * @version : 1.0
 */
public class LinkedListSingle<E> implements LinkedList<E> {

    //当前链表长度
    private int length = 0;

    //头节点
    private LinkedList.Node<E> header;

    private LinkedList.Node<E> footer;

    public LinkedListSingle() {
        this.header = new Node<>();
        this.footer = this.header;
    }

    /**
     * 添加一个元素到链表尾节点
     *
     * @param val
     */
    @Override
    public void add(E val) {
        LinkedList.Node<E> node = new Node<>(val);
        this.footer.addNext(node);
        this.footer = node;
        this.length ++;
    }

    /**
     * 添加一个元素到指定位置
     *
     * @param index
     * @param val
     */
    @Override
    public void add(int index, E val) {
        LinkedList.Node<E> before = this.getBeforeNode(index);
        //插入
        LinkedList.Node<E> node = new Node<>(val);
        node.addNext(before.next());
        before.addNext(node);
        this.length++;
    }

    /**
     * 获取链表尾元素
     *
     * @return
     */
    @Override
    public E get() {
        return this.footer.getValue();
    }

    /**
     * 获取头结点开始，指定位置元素
     *
     * @param index
     * @return
     */
    @Override
    public E get(int index) {
        return this.getBeforeNode(index).getValue();
    }

    /**
     * 返回链表长度
     *
     * @return
     */
    @Override
    public int size() {
        return this.length;
    }

    /**
     * 删除链表尾元素
     */
    @Override
    public E remove() {
        return this.remove(this.length - 1);
    }

    /**
     * 删除从链表头开始指定位置元素
     *
     * @param index
     * @return
     */
    @Override
    public E remove(int index) {
        LinkedList.Node<E> before = this.getBeforeNode(index);
        //要删除的元素
        LinkedList.Node<E> target = before.next();
        //目标的下一个节点
        LinkedList.Node<E> after = target.next();
        if (this.footer.equals(target)){
            this.footer = before;
        }
        before.addNext(after);
        this.length--;
        return target.getValue();
    }

    /**
     * 清空链表
     */
    @Override
    public void clear() {
        this.header.addNext(null);
        this.footer = this.header;
        this.length = 0;
    }

    /**
     * 遍历
     *
     * @param action
     */
    @Override
    public void forEach(Consumer<? super E> action) {
        for (LinkedList.Node header = this.header.next(); header != null; header = header.next()){
            action.accept((E)header.getValue());
        }
    }

    @Override
    public void print() {
        if (null == header.next()){
            System.out.println("当前链表为空 O_O||");
            return;
        }
        System.out.print( " \n =>");
        LinkedList.Node<E> temp = header.next();
        while (null != temp){
            System.out.print( " ~ " + temp.getValue());
            temp = temp.next();
        }
        System.out.println( "\n");
    }

    /**
     * 获取指定索引的前节点
     * @param index 索引
     * @return
     */
    private LinkedList.Node<E> getBeforeNode(int index){
        if (index > this.length){
            throw new RuntimeException("当前链表长度为:" + this.length+ " 索引位置超范围");
        }
        if(index == 0){
            return this.header;
        }
        LinkedList.Node<E> temp = header.next();
        while (--index > 0){
            temp = temp.next();
        }
        return temp;
    }

    static class Node<E> implements LinkedList.Node<E>{

        //当前节点值
        E val;

        //下个节点
        LinkedList.Node<E> next;

        Node() {}

        Node(E val) {
            this.val = val;
        }

        @Override
        public E getValue() {
            return val;
        }

        @Override
        public void addNext(LinkedList.Node<E> next) {
            this.next = next;
        }

        @Override
        public LinkedList.Node<E> next() {
            return next;
        }
    }
}
